use std::{env, fs};
use std::path::PathBuf;
use crate::http_headers::HttpHeader;
use crate::http_request::HttpRequest;
use crate::http_response::{HttpResponse, ResponseBody, ResponseStatusLine};
use crate::constants;

/// 处理回响请求，Path参数中获取需要相应给客户端的数据
pub fn handle_echo_request<'a>(request: &HttpRequest) -> HttpResponse<'a> {
    let mut echo_response = HttpResponse::new(ResponseStatusLine::success("OK"));
    let echo_content = request.request_line.uri.replace("/echo/", "");
    echo_response.add_header(HttpHeader::from_str(constants::CONTENT_TYPE, constants::TEXT_PLAIN_CONTENT));
    echo_response.add_header(HttpHeader::from_num(constants::CONTENT_LENGTH, echo_content.as_bytes().len()));
    echo_response.body = Some(ResponseBody::StrBody(echo_content));
    echo_response
}

/// 处理回响User-Agent请求头请求，从请求头中获取User-Agent参数并响应给客户端
pub fn handle_user_agent_request<'a>(request: &HttpRequest) -> HttpResponse<'a> {
    let mut user_agent_response = HttpResponse::new(ResponseStatusLine::success("OK"));
    user_agent_response.add_header(HttpHeader::from_str(constants::CONTENT_TYPE, constants::TEXT_PLAIN_CONTENT));
    let user_agent_header = request.headers.iter().find(|r| r.0.eq(&constants::USER_AGENT));
    let echo_content = match user_agent_header {
        None => "".to_string(),
        Some(h) => h.1.to_string()
    };
    user_agent_response.add_header(HttpHeader::from_num(constants::CONTENT_LENGTH, echo_content.as_bytes().len()));
    user_agent_response.body = Some(ResponseBody::StrBody(echo_content));
    user_agent_response
}

/// 校验成功返回路径,不成功则返回None
fn common_file_request(request: &HttpRequest) -> Option<PathBuf> {
    let env_args: Vec<String> = env::args().collect();
    let file_name = request.request_line.uri.replace("/files/", "");
    //获取文件名称
    if env_args.len() < 2 || file_name.is_empty()  {
        return None;
    }
    let mut file_path = PathBuf::from(env_args[2].clone());
    file_path.push(file_name.trim());
    Some(file_path)
}

/// 处理文件下载请求
pub fn handle_get_file_request<'a>(request: &HttpRequest) -> HttpResponse<'a> {
    let file_path = common_file_request(request);
    if file_path.is_none() {
        return HttpResponse::new(ResponseStatusLine::error(404, "Not Found"));
    }

    let file = fs::read_to_string(file_path.unwrap());
    match file {
        Err(_) => HttpResponse::new(ResponseStatusLine::error(404, "Not Found")),
        Ok(file_content) => {
            let mut file_response = HttpResponse::new(ResponseStatusLine::success("OK"));
            file_response.add_header(HttpHeader::from_str(constants::CONTENT_TYPE, constants::OBJECT_STREAM_CONTENT));
            file_response.add_header(HttpHeader::from_num(constants::CONTENT_LENGTH, file_content.as_bytes().len()));
            file_response.body = Some(ResponseBody::StrBody(file_content));
            file_response
        }
    }
}

/// 处理文件内容写入请求
pub fn handle_post_file_request<'a>(request: &HttpRequest) -> HttpResponse<'a> {
    let file_path = common_file_request(request);
    if file_path.is_none() {
        return HttpResponse::new(ResponseStatusLine::error(404, "Not Found"));
    }

    let write_result = fs::write(file_path.unwrap(), request.body.as_str());
    match write_result {
        Err(_) => HttpResponse::new(ResponseStatusLine::error(500, "Internal Server Error")),
        Ok(_) => HttpResponse::new(ResponseStatusLine::new("HTTP/1.1", 201, "Created"))
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    pub fn test_handle_echo_request() {
        let raw_request = "GET /echo/foo HTTP/1.1\r\nHost: localhost:4221\r\nUser-Agent: mango/pear\r\n\r\n";
        let http_request = HttpRequest::from(raw_request);
        let http_response = handle_echo_request(&http_request);
        assert_eq!("foo", http_response.body);
    }

    /// 测试回响User-Agent请求头请求
    #[test]
    pub fn test_handle_user_agent_request() {
        let raw_request = "GET /user-agent HTTP/1.1\r\nHost: localhost:4221\r\nUser-Agent: mango/pear\r\n\r\n";
        let http_request = HttpRequest::from(raw_request);
        let http_response = handle_user_agent_request(&http_request);
        assert_eq!("mango/pear", http_response.body);
    }
}